﻿using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using MediaAssistant.DAL.Constants;
using Newtonsoft.Json.Linq;

namespace MediaAssistant.DAL
{
    public partial class Movie
    {
        private int _index;
        public int Index
        {
            get
            {
                return _index;
            }
            set
            {
                _index = value;
                OnPropertyChanged("Index");
            }
        }

        public string GetFileToPlay()
        {
            if (File.Exists(FullPath))
                return FullPath;
            var alternativeLocation = AlternativeLocations.FirstOrDefault(al => File.Exists(al.Location));
            return alternativeLocation != null ? alternativeLocation.Location : null;
        }

        public bool IsLocal
        {
            get { return FullPath != null; }
        }

        partial void OnFullPathChanged()
        {
            OnPropertyChanged("IsLocal");
        }

        public Movie()
        {
            Genres=new ObservableCollection<LibraryItem>();
            Directors=new ObservableCollection<LibraryItem>();
            Writers=new ObservableCollection<LibraryItem>();
            Stars=new ObservableCollection<LibraryItem>();
        }

        private ObservableCollection<LibraryItem> _genres;
        public ObservableCollection<LibraryItem> Genres
        {
            get { return _genres; }
            set
            {
                _genres = value;
                OnPropertyChanged("Genres");
            }
        }

        private ObservableCollection<LibraryItem> _directors;
        public ObservableCollection<LibraryItem> Directors
        {
            get { return _directors; }
            set
            {
                _directors = value;
                OnPropertyChanged("Directors");
            }
        }

        private ObservableCollection<LibraryItem> _writers;
        public ObservableCollection<LibraryItem> Writers
        {
            get { return _writers; }
            set
            {
                _writers = value;
                OnPropertyChanged("Writers");
            }
        }

        private ObservableCollection<LibraryItem> _stars;
        public ObservableCollection<LibraryItem> Stars
        {
            get { return _stars; }
            set
            {
                _stars = value;
                OnPropertyChanged("Stars");
            }
        }

        private bool _isNew;
        public bool IsNew
        {
            get
            {
                return _isNew;
            }
            set
            {
                _isNew = value;
                OnPropertyChanged("IsNew");
            }
        }

        private bool _isStarred;
        public bool IsStarred
        {
            get { return _isStarred; }
            set
            {
                _isStarred = value;
                OnPropertyChanged("IsStarred");
            }
        }

        private bool _watched;

        public bool Watched
        {
            get { return _watched; }
            set
            {
                _watched = value;
                if (value)
                    IsInWishList = false;
                OnPropertyChanged("Watched");
            }
        }

        private bool _isInWishList;
        public bool IsInWishList
        {
            get { return _isInWishList; }
            set
            {
                _isInWishList = value;
                OnPropertyChanged("IsInWishList");
            }
        }

        public void UpdateLibraryInformation()
        {
            Genres.Clear();
            Writers.Clear();
            Directors.Clear();
            Stars.Clear();
            foreach (var libraryItem in LibraryItems)
            {
                switch (libraryItem.Type)
                {
                    case LibraryItemType.MovieGenre:
                        Genres.Add(libraryItem);
                        break;
                    case LibraryItemType.Writer:
                        Writers.Add(libraryItem);
                        break;
                    case LibraryItemType.Director:
                        Directors.Add(libraryItem);
                        break;
                    case LibraryItemType.Actor:
                        Stars.Add(libraryItem);
                        break;
                }
                
            }
        }

        private bool _isVisible;
        public bool IsVisible
        {
            get { return _isVisible; }
            set
            {
                _isVisible = value;
                OnPropertyChanged("IsVisible");
            }
        }
        public override string ToString()
        {
            return Title;
        }
        public void UpdateMovie(JObject jsonObject)
        {
            Title = (string)jsonObject.SelectToken("Title");
            int year;
            if (Int32.TryParse((string)jsonObject.SelectToken("Year"), out year))
            {
                Year = year;
            }
            Rated = (string)jsonObject.SelectToken("Rated");
            DateTime released;
            if (DateTime.TryParse((string)jsonObject.SelectToken("Released"), out released))
            {
                Released = released;
            }
            Plot = (string)jsonObject.SelectToken("Plot");
            Poster = (string)jsonObject.SelectToken("Poster");
            Runtime = (string)jsonObject.SelectToken("Runtime");
            decimal rating;
            if (decimal.TryParse((string)jsonObject.SelectToken("imdbRating"), out rating))
            {
                Rating = rating;
            }
            int votes;
            if (int.TryParse(((string)jsonObject.SelectToken("imdbVotes")).Replace(",",""), out votes))
            {
                Votes = votes;
            }
            IMDBId = (string)jsonObject.SelectToken("imdbID");
            CalculateWeightedRating();
        }

        public bool CanShow(bool showDrivesMoviesOnly)
        {
            return showDrivesMoviesOnly == false || IsLocal;
        }

        public ProfileMovie GetProfileMovie(Profile selectedProfile)
        {
            return ProfileMovies.FirstOrDefault(pm => pm.ProfileId == selectedProfile.Id);
        }

        private const double MinimumVoteRequired = 3000;
        private const double MeanVote = 6.9;
        public void CalculateWeightedRating()
        {
            WeightedRating = 0;
            if(Votes.HasValue==false)
                return;
            if(Rating.HasValue==false)
                return;
            WeightedRating = (decimal?) ((Votes.Value/(Votes.Value + MinimumVoteRequired))*(double) Rating + (MinimumVoteRequired/(Votes.Value + MinimumVoteRequired))*MeanVote);
        }
    }
}
